#include <opencv2/opencv.hpp>
#include <opencv2/highgui/highgui.hpp>
#include <iostream>
#include <list>
#include <string>
#include <vector>
#include <ipa_room_segmentation/distance_segmentation.h>
#include <ipa_room_segmentation/morphological_segmentation.h>
#include <ipa_room_segmentation/voronoi_segmentation.h>
#include <ipa_room_segmentation/adaboost_classifier.h>
#include <ipa_room_segmentation/voronoi_random_field_segmentation.h>

// parameters
// limits for the room-areas
double room_upper_limit_morphological_, room_upper_limit_distance_,
        room_upper_limit_voronoi_, room_upper_limit_semantic_,
        room_upper_limit_voronoi_random_, room_upper_limit_passthrough_;
double room_lower_limit_morphological_, room_lower_limit_distance_,
        room_lower_limit_voronoi_, room_lower_limit_semantic_,
        room_lower_limit_voronoi_random_, room_lower_limit_passthrough_;
// this variable selects the algorithm for room segmentation,
// 1 = morphological segmentation
// 2 = distance segmentation
// 3 = Voronoi segmentation
// 4 = semantic segmentation
// 5 = voronoi-random-field segmentation
// 99 = pass through segmentation
// Boolean to say if the algorithm needs to be trained
bool train_semantic_ = false, train_vrf_ = false;
//Boolean to say if the training of the semantic algorithm should load precomputed features
bool load_semantic_features_ = false;
//Variable for the Voronoi method that specifies the neighborhood that is looked at for critical Point extraction
int voronoi_neighborhood_index_;
//Variable that specifies the neighborhood for the vrf-segmentation.
int voronoi_random_field_epsilon_for_neighborhood_;
//number of iterations for search of neighborhood in voronoi method and vrf method
int max_iterations_;
//Variable that stores the minimum size of a neighborhood, used for the vrf method.
int min_neighborhood_size_;
//Variable that shows how near two nodes of the conditional random field can be in the vrf method. [pixel]
double min_voronoi_random_field_node_distance_;
//Variable that shows how many iterations should max. be done when infering in the conditional random field.
int max_voronoi_random_field_inference_iterations_;
//Variable that sets the minimal distance between two critical Points before one gets eliminated
double min_critical_point_distance_factor_;
//Variable that shows the maximal area of a room that should be merged with its surrounding rooms
double max_area_for_merging_;
// vector that saves the found doorway points, when using the 5th algorithm (vrf)
std::vector<cv::Point> doorway_points_;
// list of files containing maps with room labels for training the semantic segmentation
std::vector<std::string> semantic_training_maps_room_file_list_
{
    "common/files/training_maps/lab_ipa_room_training_map.png",
    "common/files/training_maps/lab_d_room_training_map.png",
    "common/files/training_maps/Freiburg52_scan_room_training.png",
    "common/files/training_maps/Freiburg52_scan_furnitures_room_training.png",
    "common/files/training_maps/lab_intel_furnitures_room_training_map.png"
};
// list of files containing maps with hallway labels for training the semantic segmentation
std::vector<std::string> semantic_training_maps_hallway_file_list_
{
    "common/files/training_maps/lab_ipa_hallway_training_map.png",
    "common/files/training_maps/lab_a_hallway_training_map.png",
    "common/files/training_maps/Freiburg52_scan_hallway_training.png",
    "common/files/training_maps/Freiburg52_scan_furnitures_hallway_training.png",
    "common/files/training_maps/lab_intel_hallway_training_map.png"
};
// list of files containing the original maps for training the VRF segmentation
std::vector<std::string> vrf_original_maps_file_list_
{
    "common/files/training_maps/voronoi_random_field_training/original_maps/Fr52_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/Fr101_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/lab_intel_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/lab_d_furnitures_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/lab_ipa_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/NLB_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/office_e_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/office_h_original.png",
    "common/files/training_maps/voronoi_random_field_training/original_maps/lab_c_furnitures_original.png"
};
// list of files containing the labeled maps for training the VRF segmentation
std::vector<std::string> vrf_training_maps_file_list_
{
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_Fr52.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_Fr101.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_intel.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_lab_d_furniture.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_lab_ipa.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_NLB_furniture.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_office_e.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_office_h.png",
    "common/files/training_maps/voronoi_random_field_training/training_maps/training_lab_c_furnitures.png"
};
// list of files containing the Voronoi maps for training the VRF segmentation - these files are optional for training and just yield a speedup
std::vector<std::string> vrf_voronoi_maps_file_list_
{
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/Fr52_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/Fr101_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/lab_intel_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/lab_d_furnitures_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/lab_ipa_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/NLB_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/office_e_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/office_h_voronoi.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_maps/lab_c_furnitures_voronoi.png"
};
// list of files containing the Voronoi node maps for training the VRF segmentation - these files are optional for training and just yield a speedup
std::vector<std::string> vrf_voronoi_node_maps_file_list_
{
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/Fr52_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/Fr101_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/lab_intel_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/lab_d_furnitures_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/lab_ipa_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/NLB_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/office_e_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/office_h_voronoi_nodes.png",
    "common/files/training_maps/voronoi_random_field_training/voronoi_node_maps/lab_c_furnitures_voronoi_nodes.png"
};

// converter-> Pixel to meter for X coordinate
double convert_pixel_to_meter_for_x_coordinate(const int pixel_valued_object_x, const float map_resolution,
                                               const cv::Point2d map_origin)
{
    return (pixel_valued_object_x * map_resolution) + map_origin.x;
}

// converter-> Pixel to meter for Y coordinate
double convert_pixel_to_meter_for_y_coordinate(int pixel_valued_object_y, const float map_resolution,
                                               const cv::Point2d map_origin)
{
    return (pixel_valued_object_y * map_resolution) + map_origin.y;
}


